#include "../common/thread_pool.hpp"
#include "server_core.hpp"
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 6666
#define MAX_CLIENTS 100

int main() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        return 1;
    }

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(server_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("bind");
        return 1;
    }

    if (listen(server_fd, SOMAXCONN) < 0) {
        perror("listen");
        return 1;
    }

    ThreadPool pool(4);
    init_server_core(&pool);

    std::cout << "[Server] Listening on port " << PORT << "..." << std::endl;

    fd_set read_fds, all_fds;
    FD_ZERO(&all_fds);
    FD_SET(server_fd, &all_fds);
    int max_fd = server_fd;

    while (true) {
        read_fds = all_fds;
        if (select(max_fd + 1, &read_fds, nullptr, nullptr, nullptr) < 0) {
            perror("select");
            break;
        }

        for (int i = 0; i <= max_fd; ++i) {
            if (FD_ISSET(i, &read_fds)) {
                if (i == server_fd) {
                    int client_fd = accept(server_fd, nullptr, nullptr);
                    if (client_fd >= 0) {
                        FD_SET(client_fd, &all_fds);
                        if (client_fd > max_fd) max_fd = client_fd;
                        register_client(client_fd);
                    }
                } else {
                    char buffer[1024] = {0};
                    int bytes_read = recv(i, buffer, sizeof(buffer) - 1, 0);
                    if (bytes_read <= 0) {
                        FD_CLR(i, &all_fds);
                        unregister_client(i);
                    } else {
                        handle_client_message(i, std::string(buffer));
                    }
                }
            }
        }
    }

    close(server_fd);
    return 0;
}

